package unimelb.discussiontracker.twitter.data.dao.impl;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.stereotype.Repository;

import unimelb.discussiontracker.twitter.common.QueryControl;
import unimelb.discussiontracker.twitter.data.dao.IHashTagRankingDao;
import unimelb.discussiontracker.twitter.data.entity.HashTagRanking;

@Repository
public class HashTagRankingDao extends GenericDataAccessObject<HashTagRanking> implements IHashTagRankingDao {

    @Override
    public HashTagRanking findByTagValueTopicAndIntervalId(String tagValue, long topicId, long intervalId) {
        final Map<String, Object> params = new HashMap<String, Object>();
        params.put("tagValue", tagValue);
        params.put("topicId", topicId);
        params.put("intervalId", intervalId);
        return this.runSingleResultNamedQuery("HashTagRanking.FindByTagValueTopicAndIntervalId", params, null);
    }

    @Override
    public long countKeywordBasedRankings(long topicId, long intervalId) {
        final Map<String, Object> params = new HashMap<String, Object>();
        params.put("topicId", topicId);
        params.put("intervalId", intervalId);
        return this.runCountQuery("HashTagRanking.CountTopRankings", params, null);
    }

    @Override
    @SuppressWarnings("unchecked")
    public List<HashTagRanking> findKeywordBasedRankings(long topicId, long intervalId, QueryControl queryControl) {
        final String query = "SELECT ranking FROM HashTagRanking ranking WHERE ranking.topic.id = :topicId AND ranking.interval.id = :intervalId";
        final String queryWithOrderPart = appendOrderPart(query, queryControl.getSortBy(), queryControl.getSortOrder());

        final Map<String, Object> params = new HashMap<String, Object>();
        params.put("topicId", topicId);
        params.put("intervalId", intervalId);
        return this.runDynamicQuery(queryWithOrderPart, params, null);
    }

    @Override
    public long countRankingsByUser(long userId, long topicId, long intervalId) {
        final Map<String, Object> params = new HashMap<String, Object>();
        params.put("userId", userId);
        params.put("topicId", topicId);
        params.put("intervalId", intervalId);
        return this.runCountQuery("HashTagRanking.CountRankingsByUser", params, null);
    }

    @Override
    public List<HashTagRanking> findRankingsByUser(long userId, long topicId, long intervalId, QueryControl queryControl) {
        final String query = "SELECT DISTINCT ranking, ranking.hashTag.value FROM HashTagRanking ranking, IN (ranking.hashTag.includingTweets) tweetAssoc WHERE tweetAssoc.tweet.owner.id = :userId AND ranking.topic.id = :topicId AND ranking.interval.id = :intervalId";
        final String queryWithOrderPart = appendOrderPart(query, queryControl.getSortBy(), queryControl.getSortOrder());

        final Map<String, Object> params = new HashMap<String, Object>();
        params.put("userId", userId);
        params.put("topicId", topicId);
        params.put("intervalId", intervalId);

        List<HashTagRanking> result = new ArrayList<HashTagRanking>();
        for (Object obj : this.runDynamicQuery(queryWithOrderPart, params, null)) {
            result.add((HashTagRanking) ((Object[]) obj)[0]);
        }
        return result;
    }

    private String appendOrderPart(String query, String sortBy, String sortOrder) {
        if ("value".equalsIgnoreCase(sortBy)) {
            return query + " ORDER BY ranking.hashTag." + sortBy + " " + sortOrder;
        } else {
            return query + " ORDER BY ranking." + sortBy + " " + sortOrder;
        }
    }

}
